import CryptoJS from 'crypto-js'
// import  './transcode.worker'
// import TransWorker from './transcode.worker'
// let Base64 = require('js-base64').Base64
import {
	XMLParser
} from 'fast-xml-parser'
import {
	Base64
} from 'js-base64'
// const transWorker =  new Worker('./transcode.worker.js')
const APPID = '1a697d4f'
const API_SECRET = 'YTYxMTYxMDZhYTc1ZDk4OTg5N2IxNzc5'
const API_KEY = 'a7fc10f04a00aeb9fc1e257d9b6252d0'

function getWebSocketUrl() {
	return new Promise((resolve, reject) => {
		// 请求地址根据语种不同变化
		var url = 'wss://ise-api.xfyun.cn/v2/open-ise'
		var host = 'ise-api.xfyun.cn'
		var apiKey = API_KEY
		var apiSecret = API_SECRET
		var date = new Date().toGMTString()
		var algorithm = 'hmac-sha256'
		var headers = 'host date request-line'
		var signatureOrigin = `host: ${host}\ndate: ${date}\nGET /v2/open-ise HTTP/1.1`
		var signatureSha = CryptoJS.HmacSHA256(signatureOrigin, apiSecret)
		var signature = CryptoJS.enc.Base64.stringify(signatureSha)
		var authorizationOrigin =
			`api_key="${apiKey}", algorithm="${algorithm}", headers="${headers}", signature="${signature}"`
		var authorization = btoa(authorizationOrigin)
		url = `${url}?authorization=${authorization}&date=${date}&host=${host}`
		resolve(url)
	})
}

export default class IseRecorder {

	constructor({
		text
	} = {}) {
		let self = this
		this.status = 'null'
		this.ent = 'en_vip'
		this.appId = APPID
		// 记录音频数据
		this.audioData = []
		// 记录评测结果
		this.resultText = ''
		// wpgs下的评测结果需要中间状态辅助记录
		this.resultTextTemp = ''
		
		// transWorker.onmessage = function(event) {
		// 	console.log(self.audioData,99999999)
		// }
		this.text = text || ''
		let scoreObj = {}
	}
	transcode(audioData) {
		let output = this.to16kHz(audioData)
		output = this.to16BitPCM(output)
		output = Array.from(new Uint8Array(output.buffer))
		this.audioData.push(...output)
	}
	to16kHz(audioData) {
		var data = new Float32Array(audioData)
		var fitCount = Math.round(data.length * (16000 / 44100))
		var newData = new Float32Array(fitCount)
		var springFactor = (data.length - 1) / (fitCount - 1)
		newData[0] = data[0]
		for (let i = 1; i < fitCount - 1; i++) {
			var tmp = i * springFactor
			var before = Math.floor(tmp).toFixed()
			var after = Math.ceil(tmp).toFixed()
			var atPoint = tmp - before
			newData[i] = data[before] + (data[after] - data[before]) * atPoint
		}
		newData[fitCount - 1] = data[data.length - 1]
		return newData
	}
	to16BitPCM(input) {
		var dataLength = input.length * (16 / 8)
		var dataBuffer = new ArrayBuffer(dataLength)
		var dataView = new DataView(dataBuffer)
		var offset = 0
		for (var i = 0; i < input.length; i++, offset += 2) {
			var s = Math.max(-1, Math.min(1, input[i]))
			dataView.setInt16(offset, s < 0 ? s * 0x8000 : s * 0x7fff, true)
		}
		return dataView
	}
	// 修改录音评测状态
	setStatus(status) {
		this.onWillStatusChange && this.status !== status && this.onWillStatusChange(this.status, status)
		this.status = status
	}
	// 连接websocket
	connectWebSocket() {
		if (APPID === 'APPID' || !APPID) {
			alert('请填写APPID、APISecret、APIKey，可从控制台-我的应用-语音评测（流式版）页面获取。')
			return false
		}
		return getWebSocketUrl().then(url => {
			let iseWS
			if ('WebSocket' in window) {
				iseWS = new WebSocket(url)
			} else if ('MozWebSocket' in window) {
				iseWS = new MozWebSocket(url)
			} else {
				alert('浏览器不支持WebSocket')
				return
			}
			this.webSocket = iseWS
			this.setStatus('init')
			iseWS.onopen = e => {
				this.setStatus('ing')
				// 重新开始录音
				setTimeout(() => {
					this.webSocketSend()
				}, 500)
			}
			iseWS.onmessage = e => {
				this.result(e.data)
			}
			iseWS.onerror = e => {
				this.recorderStop()
			}
			iseWS.onclose = e => {
				this.recorderStop()
			}
		})
	}
	// 初始化浏览器录音
	recorderInit() {
		navigator.getUserMedia =
			navigator.getUserMedia ||
			navigator.webkitGetUserMedia ||
			navigator.mozGetUserMedia ||
			navigator.msGetUserMedia

		// 创建音频环境
		try {
			this.audioContext = new(window.AudioContext || window.webkitAudioContext)()
			this.audioContext.resume()
			if (!this.audioContext) {
				alert('浏览器不支持webAudioApi相关接口')
				return
			}
		} catch (e) {
			if (!this.audioContext) {
				alert('浏览器不支持webAudioApi相关接口')
				return
			}
		}

		// 获取浏览器录音权限
		if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
			navigator.mediaDevices
				.getUserMedia({
					audio: true,
					video: false,
				})
				.then(stream => {
					this.stream = stream
					getMediaSuccess(stream)
				})
				.catch(e => {
					getMediaFail(e)
				})
		} else if (navigator.getUserMedia) {
			navigator.getUserMedia({
					audio: true,
					video: false,
				},
				stream => {
					this.stream = stream
					getMediaSuccess(stream)
				},
				function(e) {
					getMediaFail(e)
				}
			)
		} else {
			if (navigator.userAgent.toLowerCase().match(/chrome/) && location.origin.indexOf('https://') < 0) {
				alert('chrome下获取浏览器录音功能，因为安全性问题，需要在localhost或127.0.0.1或https下才能获取权限')
			} else {
				alert('无法获取浏览器录音功能，请升级浏览器或使用chrome')
			}
			this.audioContext && this.audioContext.close()
			return
		}
		// 获取浏览器录音权限成功的回调
		let getMediaSuccess = stream => {
			// console.log('getMediaSuccess')
			// 创建一个用于通过JavaScript直接处理音频
			this.scriptProcessor = this.audioContext.createScriptProcessor(0, 1, 1)
			this.scriptProcessor.onaudioprocess = e => {
				// 去处理音频数据
				if (this.status === 'ing') {
					this.transcode(e.inputBuffer.getChannelData(0))
					// transWorker.postMessage(e.inputBuffer.getChannelData(0))
				}
			}
			// 创建一个新的MediaStreamAudioSourceNode 对象，使来自MediaStream的音频可以被播放和操作
			this.mediaSource = this.audioContext.createMediaStreamSource(stream)
			// 连接
			this.mediaSource.connect(this.scriptProcessor)
			this.scriptProcessor.connect(this.audioContext.destination)
			this.connectWebSocket()
		}

		let getMediaFail = (e) => {
			alert('请求麦克风失败')
			this.audioContext && this.audioContext.close()
			this.audioContext = undefined
			// 关闭websocket
			if (this.webSocket && this.webSocket.readyState === 1) {
				this.webSocket.close()
			}
		}

	}



	recorderStart() {
		if (!this.audioContext) {
			this.recorderInit()
		} else {
			this.audioContext.resume()
			this.connectWebSocket()
		}
	}
	// 暂停录音
	recorderStop() {
		// safari下suspend后再次resume录音内容将是空白，设置safari下不做suspend
		if (!(/Safari/.test(navigator.userAgent) && !/Chrome/.test(navigator.userAgen))) {
			this.audioContext && this.audioContext.suspend()
		}
		
		this.setStatus('end')
	}
	//清除录音
	trackStop(){
		if (this.stream) {
			this.stream.getTracks().forEach(track => track.stop())
		}
	}
	
	
	// 对处理后的音频数据进行base64编码
	toBase64(buffer) {
		var binary = ''
		var bytes = new Uint8Array(buffer)
		var len = bytes.byteLength
		for (var i = 0; i < len; i++) {
			binary += String.fromCharCode(bytes[i])
		}
		return window.btoa(binary)
	}

	// 向webSocket发送数据
	webSocketSend() {
		var that = this
		if (this.webSocket.readyState !== 1) {
			return
		}
		let audioData = this.audioData.splice(0, 1280)
		var params = {
			common: {
				app_id: this.appId,
			},
			business: {
				category: 'read_sentence', // read_syllable/单字朗读，汉语专有 read_word/词语朗读  read_sentence/句子朗读 https://www.xfyun.cn/doc/Ise/IseAPI.html#%E6%8E%A5%E5%8F%A3%E8%B0%83%E7%94%A8%E6%B5%81%E7%A8%8B
				rstcd: 'utf8',
				group: 'pupil',
				sub: 'ise',
				tte: 'utf-8',
				cmd: 'ssb',
				auf: 'audio/L16;rate=16000',
				ent: that.ent,
				aus: 1,
				aue: 'raw',
				text: '\uFEFF' + that.text.toLowerCase() || '',
				ise_unite: '1',
				rst: 'entirety',
				extra_ability: 'multi_dimension'
			},
			data: {
				status: 0,
				encoding: 'raw',
				data_type: 1,
				data: this.toBase64(audioData),
			},
		}
		this.webSocket.send(JSON.stringify(params))
		this.handlerInterval = setInterval(() => {
			// websocket未连接
			if (this.webSocket.readyState !== 1) {
				this.audioData = []
				clearInterval(this.handlerInterval)
				return
			}
			// 最后一帧
			if (this.audioData.length === 0) {
				if (this.status === 'end') {
					this.webSocket.send(
						JSON.stringify({
							business: {
								cmd: 'auw',
								aus: 4,
								aue: 'raw'
							},
							data: {
								status: 2,
								encoding: 'raw',
								data_type: 1,
								data: '',
							},
						})
					)
					this.audioData = []
					clearInterval(this.handlerInterval)
				}
				return false
			}
			audioData = this.audioData.splice(0, 1280)
			// 中间帧
			this.webSocket.send(
				JSON.stringify({
					business: {
						cmd: 'auw',
						aus: 2,
						aue: 'raw'
					},
					data: {
						status: 1,
						encoding: 'raw',
						data_type: 1,
						data: this.toBase64(audioData),
					},
				})
			)
		}, 40)
	}

	result(resultData) {
		// 识别结束
		let jsonData = JSON.parse(resultData)
		if (jsonData.data && jsonData.data.data) {
			let data = Base64.decode(jsonData.data.data)
			const parser = new XMLParser({
				attributeNamePrefix: '',
				ignoreAttributes: false,
				allowBooleanAttributes: true,
			})
			const grade = parser.parse(data)
			console.log(grade, 'grade结束的这一次')
			this.scoreObj = {
				accuracy_score: grade.xml_result.read_sentence.rec_paper.read_chapter.accuracy_score, //准确度分
				fluency_score: grade.xml_result.read_sentence.rec_paper.read_chapter.fluency_score, //流畅度分
				integrity_score: grade.xml_result.read_sentence.rec_paper.read_chapter.integrity_score, //完整度分
				total_score: grade.xml_result.read_sentence.rec_paper.read_chapter.total_score //总分
			}
		}
		if (jsonData.code === 0 && jsonData.data.status === 2) {
			this.webSocket.close()
		}
		if (jsonData.code !== 0) {
			this.webSocket.close()
		}
	}

	start() {
		this.recorderStart()
	}
	stop() {
		this.recorderStop()
	}
	getScoreObj() {
		return this.scoreObj
	}

}